/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
 * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

/**
 * @file class_pad.h
 * @brief Pad object description
 */

#ifndef PAD_H_
#define PAD_H_


#include <class_board_item.h>
#include <class_board_connected_item.h>
#include <pad_shapes.h>
#include <PolyLine.h>
#include <config_params.h>       // PARAM_CFG_ARRAY
#include "zones.h"


class LINE_READER;
class EDA_3D_CANVAS;
class EDA_DRAW_PANEL;
class MODULE;
class TRACK;
class MSG_PANEL_INFO;

namespace KIGFX
{
    class VIEW;
};

// Helper class to store parameters used to draw a pad
class PAD_DRAWINFO
{
public:
    EDA_DRAW_PANEL* m_DrawPanel;  // the EDA_DRAW_PANEL used to draw a PAD ; can be null
    GR_DRAWMODE m_DrawMode;       // the draw mode
    COLOR4D m_Color;              // color used to draw the pad shape , from pad layers and
                                  // visible layers
    COLOR4D m_HoleColor;          // color used to draw the pad hole
    COLOR4D m_NPHoleColor;        // color used to draw a pad Not Plated hole
    int m_PadClearance;           // clearance value, used to draw the pad area outlines
    wxSize m_Mask_margin;         // margin, used to draw solder paste when only one layer is shown
    bool m_Display_padnum;        // true to show pad number
    bool m_Display_netname;       // true to show net name
    bool m_ShowPadFilled;         // true to show pad as solid area, false to show pas in
                                  // sketch mode
    bool m_ShowNCMark;            // true to show pad not connected mark
    bool m_ShowNotPlatedHole;     // true when the pad hole in not plated, to draw a specific
                                  // pad shape
    bool m_IsPrinting;            // true to print, false to display on screen.
    wxPoint m_Offset;             // general draw offset

    PAD_DRAWINFO();
};


class D_PAD : public BOARD_CONNECTED_ITEM
{
public:
    static int  m_PadSketchModePenSize; ///< Pen size used to draw pads in sketch mode
                                        ///< (mode used to print pads on silkscreen layer)

public:
    D_PAD( MODULE* parent );

    // Do not create a copy constructor & operator=.
    // The ones generated by the compiler are adequate.

    /* Default layers used for pads, according to the pad type.
     * this is default values only, they can be changed for a given pad
     */
    static LSET StandardMask();     ///< layer set for a through hole pad
    static LSET SMDMask();          ///< layer set for a SMD pad on Front layer
    static LSET ConnSMDMask();      ///< layer set for a SMD pad on Front layer
                                    ///< used for edge board connectors
    static LSET UnplatedHoleMask(); ///< layer set for a mechanical unplated through hole pad

    static inline bool ClassOf( const EDA_ITEM* aItem )
    {
        return aItem && PCB_PAD_T == aItem->Type();
    }

    D_PAD* Next() const       { return static_cast<D_PAD*>( Pnext ); }

#ifdef PCBNEW_WITH_TRACKITEMS
    void SetParent( EDA_ITEM* aParent ); //Hide EDA_ITEM SetParent.
#endif
    MODULE* GetParent() const { return (MODULE*) m_Parent; }

    /**
     * Imports the pad settings from aMasterPad.
     * The result is "this" has the same settinds (sizes, shapes ... )
     * as aMasterPad
     * @param aMasterPad = the template pad
     */
    void ImportSettingsFromMaster( const D_PAD& aMasterPad );

    /**
     * @return true if the pad has a footprint parent flipped
     * (on the back/bottom layer)
     */
    bool IsFlipped() const;

    /**
     * Set the pad name (sometimes called pad number, although
     * it can be an array ref like AA12
     * the pad name is limited to 4 ASCII chars
     */
    void SetPadName( const wxString& name );    // Change pad name

    /**
     * @return the pad name
     * the pad name is limited to 4 ASCII chars
     */
    wxString GetPadName() const;

    /**
     * @return the pad name in a wxUint32 which is possible
     * because the pad name is limited to 4 ASCII chars
     * The packed pad name should be used only to compare 2
     * pad names, not to try to print this name
     */
    wxUint32 GetPackedPadName() const { return m_NumPadName; }

    /**
     * Function IncrementPadName
     *
     * Increments the pad name to the next available name in the module.
     *
     * @param aSkipUnconnectable skips any pads that are not connectable (for example NPTH)
     * @param aFillSequenceGaps if true, the next reference in a sequence
     * like A1,A3,A4 will be A2. If false, it will be A5.
     * @return pad name incremented
     */
    bool IncrementPadName( bool aSkipUnconnectable, bool aFillSequenceGaps );

    bool PadNameEqual( const D_PAD* other ) const
    {
        return m_NumPadName == other->m_NumPadName; // hide tricks behind sensible API
    }

    /**
     * Function GetShape
     * @return the shape of this pad.
     */
    PAD_SHAPE_T GetShape() const                { return m_padShape; }
    void SetShape( PAD_SHAPE_T aShape )         { m_padShape = aShape; m_boundingRadius = -1; }

    void SetPosition( const wxPoint& aPos ) override { m_Pos = aPos; }
    const wxPoint& GetPosition() const override { return m_Pos; }

    void SetY( int y )                          { m_Pos.y = y; }
    void SetX( int x )                          { m_Pos.x = x; }

    void SetPos0( const wxPoint& aPos )         { m_Pos0 = aPos; }
    const wxPoint& GetPos0() const              { return m_Pos0; }

    void SetY0( int y )                         { m_Pos0.y = y; }
    void SetX0( int x )                         { m_Pos0.x = x; }

    void SetSize( const wxSize& aSize )         { m_Size = aSize;  m_boundingRadius = -1; }
    const wxSize& GetSize() const               { return m_Size; }

    void SetDelta( const wxSize& aSize )        { m_DeltaSize = aSize;  m_boundingRadius = -1; }
    const wxSize& GetDelta() const              { return m_DeltaSize; }

    void SetDrillSize( const wxSize& aSize )    { m_Drill = aSize; }
    const wxSize& GetDrillSize() const          { return m_Drill; }

    void SetOffset( const wxPoint& aOffset )    { m_Offset = aOffset; }
    const wxPoint& GetOffset() const            { return m_Offset; }


    void Flip( const wxPoint& aCentre ) override;


    /**
     * Function SetOrientation
     * sets the rotation angle of the pad.
     * @param aAngle is tenths of degrees, but will soon be degrees.  If it is
     *  outside of 0 - 3600, then it will be normalized before being saved.
     */
    void SetOrientation( double aAngle );

    /**
     * Set orientation in degrees
     */
    void SetOrientationDegrees( double aOrientation ) { SetOrientation( aOrientation*10.0 ); }

    /**
     * Function GetOrientation
     * returns the rotation angle of the pad in tenths of degrees, but soon degrees.
     */
    double GetOrientation() const { return m_Orient; }
    double GetOrientationDegrees() const   { return m_Orient/10.0; }
    double GetOrientationRadians() const   { return m_Orient*M_PI/1800; }

    void SetDrillShape( PAD_DRILL_SHAPE_T aDrillShape )
        { m_drillShape = aDrillShape; }

    PAD_DRILL_SHAPE_T GetDrillShape() const     { return m_drillShape; }

    /**
     * Function GetOblongDrillGeometry calculates the start point, end point and width
     * of an equivalent segment which have the same position and width as the hole
     * Usefull to plot/draw oblong holes like segments with rounded ends
     * used in draw and plot functions
     * @param aStartPoint = first point of the equivalent segment, relative to the pad position.
     * @param aEndPoint = second point of the equivalent segment, relative to the pad position.
     * @param aWidth = width equivalent segment.
     */
    void GetOblongDrillGeometry( wxPoint& aStartPoint, wxPoint& aEndPoint, int& aWidth ) const;

    void SetLayerSet( LSET aLayerMask )         { m_layerMask = aLayerMask; }
    LSET GetLayerSet() const override           { return m_layerMask; }

    void SetAttribute( PAD_ATTR_T aAttribute );
    PAD_ATTR_T GetAttribute() const             { return m_Attribute; }

    void SetPadToDieLength( int aLength )       { m_LengthPadToDie = aLength; }
    int GetPadToDieLength() const               { return m_LengthPadToDie; }

    int GetLocalSolderMaskMargin() const        { return m_LocalSolderMaskMargin; }
    void SetLocalSolderMaskMargin( int aMargin ) { m_LocalSolderMaskMargin = aMargin; }

    int GetLocalClearance() const               { return m_LocalClearance; }
    void SetLocalClearance( int aClearance )    { m_LocalClearance = aClearance; }

    int GetLocalSolderPasteMargin() const       { return m_LocalSolderPasteMargin; }
    void SetLocalSolderPasteMargin( int aMargin ) { m_LocalSolderPasteMargin = aMargin; }

    double GetLocalSolderPasteMarginRatio() const { return m_LocalSolderPasteMarginRatio; }
    void SetLocalSolderPasteMarginRatio( double aRatio ) { m_LocalSolderPasteMarginRatio = aRatio; }


    /**
     * Function TransformShapeWithClearanceToPolygon
     * Convert the pad shape to a closed polygon
     * Used in filling zones calculations
     * Circles and arcs are approximated by segments
     * @param aCornerBuffer = a buffer to store the polygon
     * @param aClearanceValue = the clearance around the pad
     * @param aCircleToSegmentsCount = the number of segments to approximate a circle
     * @param aCorrectionFactor = the correction to apply to circles radius to keep
     * clearance when the circle is approximated by segment bigger or equal
     * to the real clearance value (usually near from 1.0)
    */
    void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
                                               int aClearanceValue,
                                               int aCircleToSegmentsCount,
                                               double aCorrectionFactor ) const;

     /**
     * Function GetClearance
     * returns the clearance in internal units.  If \a aItem is not NULL then the
     * returned clearance is the greater of this object's clearance and
     * aItem's clearance.  If \a aItem is NULL, then this objects clearance
     * is returned.
     * @param aItem is another BOARD_CONNECTED_ITEM or NULL
     * @return int - the clearance in internal units.
     */
    int GetClearance( BOARD_CONNECTED_ITEM* aItem = NULL ) const override;

   // Mask margins handling:

    /**
     * Function GetSolderMaskMargin
     * @return the margin for the solder mask layer
     * usually > 0 (mask shape bigger than pad
     * value is
     * 1 - the local value
     * 2 - if null, the parent footprint value
     * 1 - if null, the global value
     */
    int GetSolderMaskMargin() const;

    /**
     * Function GetSolderPasteMargin
     * @return the margin for the solder mask layer
     * usually < 0 (mask shape smaller than pad
     * because the margin can be dependent on the pad size, the margin has a x and a y value
     * value is
     * 1 - the local value
     * 2 - if null, the parent footprint value
     * 1 - if null, the global value
     */
    wxSize GetSolderPasteMargin() const;

    void SetZoneConnection( ZoneConnection aType ) { m_ZoneConnection = aType; }
    ZoneConnection GetZoneConnection() const;

    void SetThermalWidth( int aWidth ) { m_ThermalWidth = aWidth; }
    int GetThermalWidth() const;

    void SetThermalGap( int aGap ) { m_ThermalGap = aGap; }
    int GetThermalGap() const;

    /* drawing functions */
    void Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC,
               GR_DRAWMODE aDrawMode, const wxPoint& aOffset = ZeroOffset ) override;

    /**
     * Function DrawShape
     * basic function to draw a pad.
     * <p>
     * This function is used by Draw after calculation of parameters (color, ) final
     * orientation transforms are set. It can also be called to draw a pad on any panel
     * even if this panel is not a EDA_DRAW_PANEL for instance on a wxPanel inside the
     * pad editor.
     * </p>
     */
    void DrawShape( EDA_RECT* aClipBox, wxDC* aDC, PAD_DRAWINFO& aDrawInfo );

    /**
     * Function BuildPadPolygon
     * Has meaning only for polygonal pads (trapezoid and rectangular)
     * Build the Corner list of the polygonal shape,
     * depending on shape, extra size (clearance ...) and orientation
     * @param aCoord = a buffer to fill (4 corners).
     * @param aInflateValue = wxSize: the clearance or margin value. value > 0:
     *                        inflate, < 0 deflate
     * @param aRotation = full rotation of the polygon
     */
    void BuildPadPolygon( wxPoint aCoord[4], wxSize aInflateValue, double aRotation ) const;

    /**
     * Function GetRoundRectCornerRadius
     * Has meaning only for rounded rect pads
     * @return The radius of the rounded corners for this pad.
     */
    int GetRoundRectCornerRadius() const
    {
        return GetRoundRectCornerRadius( m_Size );
    }

    /**
     * Helper function GetRoundRectCornerRadius
     * Has meaning only for rounded rect pads
     * Returns the radius of the rounded corners of a rectangle
     * size aSize, using others setting of the pad
     * @param aSize = size of the of the round rect. Usually the pad size
     * but can be the size of the pad on solder mask or solder paste
     * @return The radius of the rounded corners for this pad size.
     */
    int GetRoundRectCornerRadius( const wxSize& aSize ) const;

    /**
     * Function BuildPadShapePolygon
     * Build the Corner list of the polygonal shape,
     * depending on shape, extra size (clearance ...) pad and orientation
     * This function is similar to TransformShapeWithClearanceToPolygon,
     * but the difference is BuildPadShapePolygon creates a polygon shape exactly
     * similar to pad shape, which a size inflated by aInflateValue
     * and TransformShapeWithClearanceToPolygon creates a more complex shape (for instance
     * a rectangular pad is converted in a rectangulr shape with ronded corners)
     * @param aCornerBuffer = a buffer to fill.
     * @param aInflateValue = the clearance or margin value.
     *              value > 0: inflate, < 0 deflate, = 0 : no change
     *              the clearance can have different values for x and y directions
     *              (relative to the pad)
     * @param aSegmentsPerCircle = number of segments to approximate a circle
     *              (used for round and oblong shapes only (16 to 32 is a good value)
     * @param aCorrectionFactor = the correction to apply to circles radius to keep
     *        the pad size/clearance when the arcs are approximated by segments
     */
    void BuildPadShapePolygon( SHAPE_POLY_SET& aCornerBuffer,
                               wxSize aInflateValue, int aSegmentsPerCircle,
                               double aCorrectionFactor ) const;

    /**
     * Function BuildPadDrillShapePolygon
     * Build the Corner list of the polygonal drill shape,
     * depending on shape pad hole and orientation
     * @param aCornerBuffer = a buffer to fill.
     * @param aInflateValue = the clearance or margin value.
     *              value > 0: inflate, < 0 deflate, = 0 : no change
     * @param aSegmentsPerCircle = number of segments to approximate a circle
     *              (used for round and oblong shapes only(16 to 32 is a good value)
     * @return false if the pad has no hole, true otherwise
     */
    bool BuildPadDrillShapePolygon( SHAPE_POLY_SET& aCornerBuffer,
                                    int aInflateValue, int aSegmentsPerCircle ) const;

    /**
     * Function BuildSegmentFromOvalShape
     * Has meaning only for OVAL (and ROUND) pads
     * Build an equivalent segment having the same shape as the OVAL shape,
     * Useful in draw function and in DRC and HitTest functions,
     *  because segments are already well handled by track tests
     * @param aSegStart = the starting point of the equivalent segment relative to the shape
     *                    position.
     * @param aSegEnd = the ending point of the equivalent segment, relative to the shape position
     * @param aRotation = full rotation of the segment
     * @param aRotation = full rotation of the segment
     * @param aMargin = a margin around the shape (for instance mask margin)
     * @return the width of the segment
     */
    int BuildSegmentFromOvalShape( wxPoint& aSegStart, wxPoint& aSegEnd,
                                   double aRotation, const wxSize& aMargin ) const;

    void StringPadName( wxString& text ) const; // Return pad name as string in a buffer

    /**
     * Function GetBoundingRadius
     * returns the radius of a minimum sized circle which fully encloses this pad.
     * The center is the pad position
     */
    int GetBoundingRadius() const
    {
        // Any member function which would affect this calculation should set
        // m_boundingRadius to -1 to re-trigger the calculation from here.
        // Currently that is only m_Size, m_DeltaSize, and m_padShape accessors.
        if( m_boundingRadius == -1 )
        {
            m_boundingRadius = boundingRadius();
        }

        return m_boundingRadius;
    }

    wxPoint ShapePos() const;

    /**
     * has meaning only for rounded rect pads
     * @return the scaling factor between the smaller Y or Y size and the radius
     * of the rounded corners.
     * Cannot be > 0.5
     * the normalized IPC-7351C value is 0.25
     */
    double GetRoundRectRadiusRatio() const
    {
        return m_padRoundRectRadiusScale;
    }

    /**
     * has meaning only for rounded rect pads
     * Set the scaling factor between the smaller Y or Y size and the radius
     * of the rounded corners.
     * Cannot be < 0.5 and obviously must be > 0
     * the normalized IPC-7351C value is 0.25
     */
    void SetRoundRectRadiusRatio( double aRadiusScale )
    {
        if( aRadiusScale < 0.0 )
            aRadiusScale = 0.0;

        m_padRoundRectRadiusScale = std::min( aRadiusScale, 0.5 );
    }

    /**
     * Function GetSubRatsnest
     * @return int - the netcode
     */
    int GetSubRatsnest() const                  { return m_SubRatsnest; }
    void SetSubRatsnest( int aSubRatsnest )     { m_SubRatsnest = aSubRatsnest; }

    void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) override;

    bool IsOnLayer( PCB_LAYER_ID aLayer ) const override
    {
        return m_layerMask[aLayer];
    }

    bool HitTest( const wxPoint& aPosition ) const override;

    bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;

    wxString GetClass() const override
    {
        return wxT( "PAD" );
    }

    // Virtual function:
    const EDA_RECT GetBoundingBox() const override;

    ///> Set absolute coordinates.
    void SetDrawCoord();

    ///> Set relative coordinates.
    void SetLocalCoord();

    /**
     * Function Compare
     * compares two pads and return 0 if they are equal.
     * @return int - <0 if left less than right, 0 if equal, >0 if left greater than right.
     */
    static int Compare( const D_PAD* padref, const D_PAD* padcmp );

    void Move( const wxPoint& aMoveVector ) override
    {
        m_Pos += aMoveVector;
        SetLocalCoord();
    }

    void Rotate( const wxPoint& aRotCentre, double aAngle ) override;

    wxString GetSelectMenuText() const override;

    BITMAP_DEF GetMenuImage() const override;

    /**
     * Function ShowPadShape
     * @return the name of the shape
     */
    wxString ShowPadShape() const;

    /**
     * Function ShowPadAttr
     * @return the name of the pad type (attribute) : STD, SMD ...
     */
    wxString ShowPadAttr() const;

    /**
     * Function AppendConfigs
     * appends to @a aResult the configuration setting accessors which will later
     * allow reading or writing of configuration file information directly into
     * this object.
     */
    void AppendConfigs( PARAM_CFG_ARRAY* aResult );

    EDA_ITEM* Clone() const override;

    /**
     * same as Clone, but returns a D_PAD item.
     * Useful mainly for pythons scripts, because Clone (virtual function)
     * returns an EDA_ITEM.
     */
    D_PAD* Duplicate() const
    {
        return (D_PAD*) Clone();
    }

    virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;

    virtual unsigned int ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;

    virtual const BOX2I ViewBBox() const override;

    /**
     * Function CopyNetlistSettings
     * copies the netlist settings to \a aPad, and the net name.
     * Used to copy some pad parameters when replacing a footprint by an other
     * footprint when reading a netlist, or in exchange footprint dialog
     *
     * The netlist settings are all of the #D_PAD settings not define by a #D_PAD in
     * a netlist.
     * The copied settings are the net name and optionally include local clearance, etc.
     * The pad physical geometry settings are not copied.
     *
     * @param aPad is the #D_PAD to copy the settings to.
     * @param aCopyLocalSettings = false to copy only the net name
     *   true to also copy local prms
     */
    void CopyNetlistSettings( D_PAD* aPad, bool aCopyLocalSettings );

#if defined(DEBUG)
    virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
#endif

#ifdef PCBNEW_WITH_TRACKITEMS
     int GetIDNumber(void) const { return m_id_number; }
#endif


private:
    
#ifdef PCBNEW_WITH_TRACKITEMS
    //ID number. To MODULE copy for, that we do not change PAD(s) address.
    int m_id_number; 
#endif
    
    /**
     * Function boundingRadius
     * returns a calculated radius of a bounding circle for this pad.
     */
    int boundingRadius() const;

private:    // Private variable members:

    // Actually computed and cached on demand by the accessor
    mutable int m_boundingRadius;  ///< radius of the circle containing the pad shape

#ifndef SWIG
    /// Pad name (4 char) or a long identifier (used in pad name
    /// comparisons because this is faster than string comparison)
    union
    {
#define PADNAMEZ    4
        char        m_Padname[PADNAMEZ];    // zero padded at end to full size
        wxUint32    m_NumPadName;           // same number of bytes as m_Padname[]
    };
#endif

    wxPoint     m_Pos;              ///< pad Position on board

    PAD_SHAPE_T m_padShape;         ///< Shape: PAD_SHAPE_CIRCLE, PAD_SHAPE_RECT,
                                    ///< PAD_SHAPE_OVAL, PAD_SHAPE_TRAPEZOID,
                                    ///< PAD_SHAPE_ROUNDRECT, PAD_SHAPE_POLYGON

    int         m_SubRatsnest;      ///< variable used in rats nest computations
                                    ///< handle subnet (block) number in ratsnest connection

    wxSize      m_Drill;            ///< Drill diam (drill shape = PAD_CIRCLE) or drill size
                                    ///< (shape = OVAL) for drill shape = PAD_CIRCLE, drill
                                    ///< diam = m_Drill.x

    wxSize      m_Size;             ///< X and Y size ( relative to orient 0)

    PAD_DRILL_SHAPE_T m_drillShape; ///< PAD_DRILL_SHAPE_CIRCLE, PAD_DRILL_SHAPE_OBLONG

    double      m_padRoundRectRadiusScale;  ///< scaling factor from smallest m_Size coord
                                            ///< to corner radius, default 0.25

    /**
     * m_Offset is useful only for oblong and rect pads (it can be used for other
     * shapes, but without any interest).
     * This is the offset between the pad hole and the pad shape (you must
     * understand here pad shape = copper area around the hole)
     * Most of cases, the hole is the center of the shape (m_Offset = 0).
     * But some board designers use oblong/rect pads with a hole moved to one of the
     * oblong/rect pad shape ends.
     * In all cases the pad position is the pad hole.
     * The physical shape position (used to draw it for instance) is pad
     * position (m_Pos) + m_Offset.
     * D_PAD::ShapePos() returns the physical shape position according to
     * the offset and the pad rotation.
     */
    wxPoint     m_Offset;

    LSET        m_layerMask;        ///< Bitwise layer :1= copper layer, 15= cmp,
                                    ///< 2..14 = internal layers
                                    ///< 16 .. 31 = technical layers

    wxSize      m_DeltaSize;        ///< delta on rectangular shapes

    wxPoint     m_Pos0;             ///< Initial Pad position (i.e. pad position relative to the
                                    ///< module anchor, orientation 0)

    PAD_ATTR_T  m_Attribute;        ///< PAD_ATTRIB_NORMAL, PAD_ATTRIB_SMD,
                                    ///< PAD_ATTRIB_CONN, PAD_ATTRIB_HOLE_NOT_PLATED
    double      m_Orient;           ///< in 1/10 degrees

    int         m_LengthPadToDie;   ///< Length net from pad to die, inside the package

    /// Local clearance. When null, the module default value is used.
    /// when the module default value is null, the netclass value is used
    /// Usually the local clearance is null
    int         m_LocalClearance;

    /// Local mask margins: when 0, the parent footprint design values are used

    int         m_LocalSolderMaskMargin;        ///< Local solder mask margin
    int         m_LocalSolderPasteMargin;       ///< Local solder paste margin absolute value

    double      m_LocalSolderPasteMarginRatio;  ///< Local solder mask margin ratio value of pad size
                                                ///< The final margin is the sum of these 2 values
    /// how the connection to zone is made: no connection, thermal relief ...
    ZoneConnection m_ZoneConnection;

    int         m_ThermalWidth;
    int         m_ThermalGap;
};

#endif  // PAD_H_
